import {
  Component,
  OnInit,
  Input,
  HostBinding,
  OnChanges,
  ContentChild,
  TemplateRef,
  Output,
} from '@angular/core';
import { MySelection } from 'app/modules/base/selection';
import { map, combineLatest } from 'rxjs/operators';
import { BehaviorSubject, Observable } from 'rxjs';

@Component({
  selector: 'm-tree',
  templateUrl: './tree.component.html',
  styleUrls: ['./tree.component.scss'],
})
export class TreeComponent<T extends { children: T[] }> implements OnInit, OnChanges {
  @Input() data: T[] = [];
  @Input() level = 0;
  @Input() selection: MySelection<T>;

  @HostBinding('hidden')
  closed = false;

  @HostBinding('class.jstree-default')
  rootClass = false;

  @Input()
  @ContentChild(TemplateRef)
  template: TemplateRef<any>;

  constructor() {}

  ngOnInit() {}

  select(item: T) {
    if (this.selection.isSelected(item)) {
      this.selection.unselect(item, ...flatTree(item.children));
    } else {
      this.selection.select(item, ...flatTree(item.children));
    }
  }

  ngOnChanges() {
    if (this.level === 0) {
      this.rootClass = true;
    }
  }
}

function flatTree<T extends { children: T[] }>(nodes: T[]): T[] {
  let arr: T[] = [];
  for (let node of nodes) {
    arr.push(node);
    if (node.children && node.children.length) {
      arr = arr.concat(flatTree(node.children));
    }
  }
  return arr;
}

export function toTree<T extends { children?: T[] }>(arr: T[], levelKey: keyof T): T[] {
  const children: T[] = [];
  const brother: T[] = [];
  let current: T;
  for (const z of arr) {
    if (!current) {
      current = z;
      continue;
    }
    if ((z[levelKey] as any).startsWith(current[levelKey])) {
      children.push(z);
      continue;
    }
    current.children = toTree(children, levelKey);
    children.length = 0;
    brother.push(current);
    current = z;
  }
  if (current) {
    current.children = toTree(children, levelKey);
    brother.push(current);
  }
  return brother;
}
